﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2014-04-20 18:00
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BassDrop.Core.Common.Data
{
	/// <summary>
	/// Base class for location specific data items
	/// </summary>
	/// <typeparam name="TParent">the type of the data container object containing this object</typeparam>
	public abstract class CustomDataItemBase<TParent>
	{
		/// <summary>
		/// The set of applications that can use this information.
		/// If empty, all clients apply.
		/// </summary>
		public HashSet<string> Clients
		{
			get;
			private set;
		}

		/// <summary>
		/// The set of locations (machines) that can use this information.
		/// If empty, all locations apply.
		/// </summary>
		public HashSet<string> LocationIds
		{
			get;
			private set;
		}

		/// <summary>
		/// The data container object containing this object
		/// </summary>
		protected TParent Parent
		{
			get;
			private set;
		}

		/// <summary>
		/// Initializes the common properties of CustomDataItemBase subclasses
		/// </summary>
		/// <param name="parent">the data container object containing this object</param>
		protected CustomDataItemBase( TParent parent )
		{
			Clients = new HashSet<string>();
			LocationIds = new HashSet<string>();
			Parent = parent;
		}

		/// <summary>
		/// Returns whether this location info applies for the passed client (application) and location (machine)
		/// </summary>
		/// <param name="client">the ID of an application. If null, all clients are considered compatible</param>
		/// <param name="location">the location ID of a machine. If null, all locations are considered compatible</param>
		/// <returns></returns>
		public bool DoesApplyFor( string client, string location )
		{
			if ( !string.IsNullOrWhiteSpace( client ) && Clients.Count > 0 && !Clients.Contains( client ) )
			{
				return false;
			}

			if ( !string.IsNullOrWhiteSpace( location ) && LocationIds.Count > 0 && !LocationIds.Contains( location ) )
			{
				return false;
			}

			return true;
		}

		/// <summary>
		/// Returns whether there is a system on which both this and the other data item is applicable
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		public bool Match( CustomDataItemBase<TParent> other )
		{
			bool clientsMatch = Clients.Count == 0 && other.Clients.Count == 0;

			foreach ( var client in other.Clients )
			{
				if ( Clients.Contains( client ) )
				{
					clientsMatch = true;
					break;
				}
			}

			if ( !clientsMatch )
			{
				return false;
			}

			if ( LocationIds.Count == 0 && other.LocationIds.Count == 0 )
			{
				return true;
			}

			foreach ( var location in other.LocationIds )
			{
				if ( LocationIds.Contains( location ) )
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Merge the other data item into this one, so that the set of clients and locations will be the union of the two
		/// </summary>
		/// <param name="other"></param>
		public void Merge( CustomDataItemBase<TParent> other )
		{
			foreach ( var item in other.Clients )
			{
				Clients.Add( item );
			}

			foreach ( var item in other.LocationIds )
			{
				LocationIds.Add( item );
			}
		}
	}
}
